// pages/kitchen-scale/kitchen-scale.js
const {
  QNMPPlugin,
  QNConsts,
  QNBleProtocols
} = requirePlugin('QNBleApi');

const {
  FasciaGunSmartProtocol
} = QNBleProtocols;

const BleOpStatusEnum = {
  // 初始状态，未init前
  NOOP: 'NOOP',
  // 蓝牙不可用
  BLE_DISABLED: 'BLE_DISABLED',
  // 蓝牙可用
  BLE_READY: 'BLE_READY',
  // 正在扫描
  SCANNING: 'SCANNING',
  // 停止扫描
  STOP_SCANNING: 'STOP_SCANNING',
  // 已发现设备
  DEVICE_FOUNDED: 'DEVICE_FOUNDED',
  // 正在连接
  CONNECTING: 'CONNECTING',
  // 已连接
  CONNECTED: 'CONNECTED',
  // 连接失败
  CONNECT_FAILED: 'CONNECT_FAILED',
  // 断开连接
  DISCONNECTED: 'DISCONNECTED',
  // 连接超时
  CONNECT_OVERTIME: 'CONNECT_OVERTIME',
  // 例如：正在测量
  OPERATING: 'OPERATING',
  // 例如：测量完成
  OPERATE_FINISHED: 'OPERATE_FINISHED',
  // 发生了错误
  ERROR_OCCURED: 'ERROR_OCCURED',
};

/**
 * 微信的本地日志功能，需要用户手动反馈才能拿到日志文件
 */
const logger = () => {
  const wxlogger =
    wx.getLogManager &&
    wx.getLogManager({
      level: 0,
    });
  const log = (...params) => {
    console.log(...params);
    wxlogger && wxlogger.log(...params);
  };
  return {
    log,
  };
};

function defaultDeviceInfo() {
  return {
    // 3、Gear：当前工作档位，范围：1-5档；0x01-1档，0x02-2档，0x03-3档，0x04-4档，0x05-AI档
    gear: 0,
    // 4、RMP：实时转速。单位：1rmp/min
    rmp: 0,
    // 5、AI-MODE：AI档模式。（1）高4bit：大模式；低4bit：小模式；（2）大模式：0--自动模式，1--曲线模式
    // (3）自动档小模式：0--放松，1--运动，2--恢复；（4）曲线档小模式：0；
    aiLargeMode: 0,
    aiSmallMode: 0,
    // 6、6、STATE：筋膜枪模式，0x00-待机模式，0x01-工作模式；
    gmqMode: false,
    // 7、TOTAL-TIME：设置的按摩总时长，单位：250ms，输出以秒输出
    totalWorkingTime: false,
    // 按摩剩余时长，单位：250ms，输出以秒输出
    remainWorkingTime: 0,
  };
}

function unitTransform(value, unit, weightPrecision = 1) {
  let calc = value;
  const isNegative = value < 0;
  switch (unit) {
    case QNConsts.QNBleUnit.FLOZ:
      calc = (0.035274 * value).toFixed(weightPrecision + 1);
      break
    case QNConsts.QNBleUnit.LBOZ:
      calc = Math.abs(0.035274 * value);
      calc = `${isNegative ? '-' : ''}${Math.floor(calc / 16)}:${(calc % 16).toFixed(weightPrecision + 1)}`;
      break
    case QNConsts.QNBleUnit.MILKML:
      calc = (value / 1.03).toFixed(weightPrecision);
      break
    case QNConsts.QNBleUnit.G:
    case QNConsts.QNBleUnit.ML:
    default:
      calc = value.toFixed(weightPrecision);
      break
  }
  return calc;
}

console.info('FasciaGunSmartProtocol', FasciaGunSmartProtocol)

Page({

  /**
   * 页面的初始数据
   */
  data: {
    deviceId: '',
    connected: false,
    connecting: false,
    bleOpStatus: BleOpStatusEnum.NOOP,
    bleOpStatusText: '初始化中...',
    // 蓝牙可用状态
    bleEnableState: false,
    controlGroup: [{
        value: 1,
        name: 'g',
      },
      {
        value: 2,
        name: 'ml',
      },
      {
        value: 4,
        name: 'ml(牛奶)',
      },
      {
        value: 8,
        name: 'fl.oz',
      },
      {
        value: 0x10,
        name: 'lb:oz',
      },
      {
        value: 0x20,
        name: '去皮',
      },
    ],
    controlRadioValue: -1,
    standbyTimeGroup: [{
        value: 1,
        name: '2分钟',
      },
      {
        value: 2,
        name: '3.5分钟',
      },
      {
        value: 3,
        name: '5分钟',
      },
    ],
    standbyTimeRadioValue: -1,
    hasReceivedScaleData: false,
    deviceInfo: defaultDeviceInfo(),
    weightText: '',
    mode: 1,
    bigMode: 0,
    smallMode: 0,
    time: 1,
    workMode: 1,
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    /**
     * 判断相关权限是否开启, 根据需求放在合适的位置
     * locationEnabled 是否开启定位
     * locationAuthorized 是否授权定位(仅安卓需要,需要选择始终允许,不能选择询问,因为微信不会询问用户是否开启定位)
     * bluetoothEnabled 蓝牙是否开启
     */
    // const { locationAuthorized, locationEnabled, bluetoothEnabled } = wx.getSystemInfoSync();
    // if (!locationAuthorized || !locationEnabled || !bluetoothEnabled) {
    //   this.tip('请确认相关权限是否开启');
    //   setTimeout(() => {
    //     wx.navigateBack();
    //   }, 2000);
    // }

    // 初始化蓝牙
    this.bleApi = new QNMPPlugin({
      useSdk: false,
      logger: logger(), // 非必须，日志功能，最好有，方便排查问题，可以替换为客户自己的
      protocols: [FasciaGunSmartProtocol],
    });

    // 错误监听
    this.bleApi.onError = (err) => {
      this.updateBleOpStatus(BleOpStatusEnum.ERROR_OCCURED);
      console.error('捕捉到错误', err.detail);
      wx.showToast({
        title: `发生了错误.[error]: ${err.message}`,
        icon: 'error',
      })
    };

    // 初始化回调
    this.bleApi.onReady = ({
      bleEnableState, // 表示当前蓝牙是否为开启状态
    }) => {
      if (bleEnableState) {
        this.updateBleOpStatus(BleOpStatusEnum.BLE_READY);
        this.setData({
          bleEnableState: true
        });
        // this.bleApi.startBleDeviceDiscovery();
      } else {
        console.log('蓝牙状态为关闭');
        this.updateBleOpStatus(BleOpStatusEnum.BLE_DISABLED);
      }
    };

    // 设置蓝牙监听事件
    this.bleApi.setBleEventListener(this.bleEventListener());

    // 初始化
    this.bleApi.init();
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    if (this.bleApi) {
      this.bleApi.stop();
    }
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },

  updateBleOpStatus(status) {
    let text = '';
    switch (status) {
      case BleOpStatusEnum.NOOP:
        text = '初始化中...';
        break;
      case BleOpStatusEnum.BLE_DISABLED:
        text = '蓝牙不可用';
        break;
      case BleOpStatusEnum.BLE_READY:
        text = '请将手机靠近设备进行连接';
        break;
      case BleOpStatusEnum.SCANNING:
        text = '正在扫描设备';
        break;
      case BleOpStatusEnum.DEVICE_FOUNDED:
        text = '已发现设备';
        break;
      case BleOpStatusEnum.CONNECTING:
        text = '正在连接...';
        break;
      case BleOpStatusEnum.STOP_SCANNING:
        text = '停止扫描';
        break;
      case BleOpStatusEnum.CONNECTED:
        text = '已连接';
        break;
      case BleOpStatusEnum.CONNECT_FAILED:
        text = '连接设备失败';
        break;
      case BleOpStatusEnum.DISCONNECTED:
        text = '断开连接';
        break;
      case BleOpStatusEnum.CONNECT_OVERTIME:
        text = '连接超时';
        break;
      case BleOpStatusEnum.OPERATING:
        text = '正在测量';
        break;
      case BleOpStatusEnum.OPERATE_FINISHED:
        text = '重量已稳定';
        break;
      case BleOpStatusEnum.ERROR_OCCURED:
        text = '发生了错误';
        break;
      default:
        break;
    }

    this.setData({
      bleOpStatus: status,
      bleOpStatusText: text,
    });
  },

  // 蓝牙相关事件回调
  bleEventListener() {
    /**
     * 监听扫描到设备的回调
     */
    const onBleDeviceFound = (device) => {
      // 测试时这里可过滤mac来方便连接
      // if (device.mac === 'FF:F2:00:06:1D:AB') {
      //   this.updateBleOpStatus(BleOpStatusEnum.DEVICE_FOUNDED);
      //   this.handleConnect(device);
      // }

      this.updateBleOpStatus(BleOpStatusEnum.DEVICE_FOUNDED);
      this.handleConnect(device);
    };

    /**
     * 监听蓝牙断开连接的回调
     */
    const onDisconnected = (device) => {
      this.updateBleOpStatus(BleOpStatusEnum.DISCONNECTED);
      this.setData({
        connected: false,
      });
      console.log('设备连接已断开', device);
    };

    /**
     * 监听蓝牙状态发生变化回调，连接成功或断开连接都会出触发
     */
    const onBluetoothEnableChange = ({
      available
    }) => {
      console.log('onBluetoothEnableChange', available);
      this.setData({
        bleEnableState: available
      });
      if (available) {
        this.updateBleOpStatus(BleOpStatusEnum.BLE_READY);
        // this.bleApi.startBleDeviceDiscovery();
      } else {
        this.updateBleOpStatus(BleOpStatusEnum.BLE_DISABLED);
      }
    };

    /**
     * 	监听设备连接成功回调
     */
    const onConnected = (device) => {
      this.updateBleOpStatus(BleOpStatusEnum.CONNECTED);
      console.log('设备已连接', device);
      this.setData({
        connected: true,
        connecting: false,
        deviceId: device.deviceId,
      });
    };

    /**
     * 监听停止扫描的回调
     */
    const onStopDiscoveryDevice = () => {
      if (this.data.bleOpStatus !== BleOpStatusEnum.CONNECTING) {
        this.updateBleOpStatus(BleOpStatusEnum.STOP_SCANNING);
      }
    };

    /**
     * 监听开始扫描设备的回调
     */
    const onStartDiscoveryDevice = () => {
      this.updateBleOpStatus(BleOpStatusEnum.SCANNING);
    };

    /**
     * 连接超时
     */
    const onConnectOverTime = () => {
      this.updateBleOpStatus(BleOpStatusEnum.CONNECT_OVERTIME);
      this.setData({
        connecting: false,
      });
    }

    return {
      onBleDeviceFound,
      onDisconnected,
      onBluetoothEnableChange,
      onConnected,
      onStopDiscoveryDevice,
      onStartDiscoveryDevice,
      onConnectOverTime,
    };
  },

  async handleConnect(device) {
    const {
      connecting
    } = this.data;
    if (connecting) {
      console.log('当前正在连接，不再处理');
      return;
    }
    this.setData({
      connecting: true
    });
    this.updateBleOpStatus(BleOpStatusEnum.CONNECTING);

    await this.bleApi.createBleConnection(device, this.deviceEventListener());
  },

  // 秤端相关事件回调
  deviceEventListener() {
    /**
     * 获取秤端数据
     * 注意这个方法会大概间隔200ms一直回调
     */
    const onGetDeviceInfo = (data) => {
      this.setData({
        deviceInfo: data.info
      })
    };

    const onGetFixedModeRmpResult = (data) => {
      console.info('data', data)
    }
    const onGetFixedModeRmpRangeResult = (data) => {
      console.info('data', data)
    }
    const onGetAiModeAutomaticRmpRangeResult = (data) => {
      console.info('data', data)
    }
    const onGetAiModeCurveRmpRangeResult = (data) => {
      console.info('data', data)
    }

    return {
      onGetDeviceInfo,
      onGetFixedModeRmpResult,
      onGetFixedModeRmpResult,
      onGetFixedModeRmpRangeResult,
      onGetAiModeAutomaticRmpRangeResult,
      onGetAiModeCurveRmpRangeResult
    };
  },

  onControlRadioGroupChange(e) {
    this.setData({
      controlRadioValue: Number(e.detail.value),
    });
  },

  onStandbyTimeRadioGroupChange(e) {
    this.setData({
      standbyTimeRadioValue: Number(e.detail.value),
    });
  },

  /**
   * 设置单位，去皮，关机等操作
   */
  doSetControl() {
    if (this.data.controlRadioValue >= 0) {
      if (this.bleApi) {
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'doSetControl', [{
          control: this.data.controlRadioValue
        }]);
      }
    } else {
      wx.showToast({
        title: '请先选择一项进行设置',
        icon: 'none',
      })
    }
  },

  /**
   * 设置待机时间
   */
  doSetStandbyTime() {
    if (this.data.standbyTimeRadioValue >= 0) {
      if (this.bleApi) {
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'doSetStandbyTime', [{
          control: this.data.standbyTimeRadioValue
        }]);
      }
    } else {
      wx.showToast({
        title: '请先选择一项进行设置',
        icon: 'none',
      })
    }
  },

  startClick() {
    if (this.bleApi) {
      this.bleApi.startBleDeviceDiscovery();
    }
  },

  stopClick() {
    if (this.bleApi) {
      this.bleApi.stop().then(() => {
        this.setData({
          scaleData: defaultScaleData(),
          weightText: '',
          hasReceivedScaleData: false
        });
      });
    }
  },

  handleGetInfo(e) {
    const name = e.currentTarget.dataset.name
    switch (name) {
      case 'getFixedModeRmp':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'getFixedModeRmp', []);
        break;
      case 'getFixedModeRmpRange':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'getFixedModeRmpRange', []);
        break;
      case 'getAiModeAutomaticRmpRange':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'getAiModeAutomaticRmpRange', []);
        break;
      case 'getAiModeCurveRmpRange':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'getAiModeCurveRmpRange', []);
        break;
      case 'setFixedModeRmp':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'setFixedModeRmp', [
          [1000, 2000, 2300, 2500]
        ]);
        break;
      case 'setMode':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'setMode', [{
          mode: this.data.mode,
          aiLargeMode: this.data.bigMode,
          aiSmallMode: this.data.smallMode
        }]);
        break;
      case 'setDeviceWorkTime':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'setDeviceWorkTime', [this.data.time]);
        break;
      case 'setDeviceWorkMode':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'setDeviceWorkMode', [this.data.workMode]);
        break;
      case 'setAiModeCurveRmpRange':
        this.bleApi.callProtocolMethodAsync(this.data.deviceId, 'setAiModeCurveRmpRange', [
          [{
            rmp: 1000,
            time: 1,
          }, {
            rmp: 1200,
            time: 1,
          }, {
            rmp: 1500,
            time: 1,
          }, {
            rmp: 1800,
            time: 1,
          }, {
            rmp: 1900,
            time: 1,
          }, {
            rmp: 1400,
            time: 1,
          }, {
            rmp: 1200,
            time: 1,
          }]
        ]);
        break;
      default:
        break;
    }
  },
  handleModeChange(e) {
    console.info('e', e)
    const value = Number(e.detail.value)
    const type = e.target.dataset.type
    if (type === 'normal') {
      this.setData({
        mode: value
      })
    }
    if (type === 'big') {
      this.setData({
        bigMode: value
      })
    }
    if (type === 'small') {
      this.setData({
        smallMode: value
      })
    }
  },
  bindTimeChange(e) {
    const value = Number(e.detail.value)
    this.setData({
      time: value
    })
  },
  handleDeviceWorkModeChange(e) {
    const value = Number(e.detail.value)
    this.setData({
      workMode: value
    })
  }
})